package com.tt.payee.log;


import com.alibaba.fastjson.JSON;
import com.tt.payee.common.Constant;
import com.tt.payee.domain.SysLog;

import com.tt.payee.service.log.SysLogService;
import com.tt.payee.utils.IpUtils;
import com.tt.payee.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;
import java.util.Objects;

/**
 * @author Tang
 * @Description: 日志输出类
 * @date:2020-03-06 18:02
 */

@Aspect
@Component
@Slf4j
public class SysLogAspect {

    @Resource
    SysLogService sysLogService;

    /**
     * 定义切点 @Pointcut
     * 在注解的位置切入代码
     */
    @Pointcut("@annotation(LogParameter)")
    public void logPoinCut() {
    }

    /**
     * 切面 配置通知
     * @param joinPoint
     */
    @AfterReturning("logPoinCut()")
    public void saveSysLog(JoinPoint joinPoint) throws Exception {

        String login = "login";

        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

        //保存日志对象
        SysLog sysLog = new SysLog();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        //获取注解
        LogParameter annotation = method.getAnnotation(LogParameter.class);
        //获取操作
        LogParameter myLog = method.getAnnotation(LogParameter.class);
        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取请求的方法名
        String methodName = method.getName();
        //请求的参数
        Object[] args = joinPoint.getArgs();


        //判断参数类型是否为文件如果为文件则替换
        for(int i = 0 ; i < args.length; i++) {

            if(args[i] instanceof MultipartFile){
                args[i] = "file";
            }
        }

        //将参数所在的数组转换成json
        String params = JSON.toJSONString(args);

        //用户名
        String name = null;

        //用户ip
        String remoteAddress = null;

        //判断是不是登陆接口
        if(login.equals(methodName)){

            String substring = params.substring(1);
            String substring1 = substring.substring(0, substring.length() - 1);
            Map mapTypes = JSON.parseObject(substring1);
            params = null;

            name = (String) mapTypes.get("username");
        }else {
            String token = request.getHeader("access_token");
            if(StringUtils.isNotBlank(token)){
                name = JwtTokenUtil.getUsernameFromToken(token);
            }
        }

        if (myLog != null) {
            String value = myLog.value();
            //保存获取的操作
            sysLog.setOperation(value);
        }

        sysLog.setMethod(className + "." + methodName);
        sysLog.setParams(params);
        sysLog.setCreateDate(new Date());
        //获取用户名
        sysLog.setUsername(name);
        //获取用户ip地址
        sysLog.setIp(IpUtils.getIpAddr(request));
        sysLog.setParticulars(annotation.value());


        try{
            //调用service保存SysLog实体类到数据库
            int result = sysLogService.addTheLog(sysLog);

            if(Constant.LOSE == result){
                log.error("日志写入失败");
            }

        }catch (Exception e){
            log.error("日志写入失败",e);
        }

    }
}
